package info.sswap.ontologies.modularity.owlapi;

import info.sswap.ontologies.modularity.Module;
import info.sswap.ontologies.modularity.ModuleExtractionException;
import info.sswap.ontologies.modularity.ModuleExtractor;

import java.net.URI;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.modularity.OntologySegmenter;
import org.semanticweb.owlapi.util.OWLOntologyImportsClosureSetProvider;
import org.semanticweb.owlapi.util.OWLOntologyMerger;

import uk.ac.manchester.cs.owlapi.modularity.ModuleType;
import uk.ac.manchester.cs.owlapi.modularity.SyntacticLocalityModuleExtractor;

/**
 * Delegates all the work to an OWL API based module extractor which is executed in the same JVM
 * 
 * @author Pavel Klinov
 *
 */
public class LocalOWLAPIModuleExtractor implements ModuleExtractor {

	private final URI mPhysicalURI;
	private final ModuleType mModuleType;
	
	public LocalOWLAPIModuleExtractor(URI ontoURI, ModuleType modType) {
		mPhysicalURI = ontoURI;
		mModuleType = modType;
	}
	
	public ModuleType getModuleType() {
		return mModuleType;
	}
	
	@Override
	public Module extract(Collection<URI> theSignature) throws ModuleExtractionException {
		
		if (theSignature.isEmpty()) return new OWLAPIModule();
		
		System.out.println("Conventional ME: extracting " + mModuleType + " module for " + theSignature + " from " + mPhysicalURI);
		
		OWLOntologyManager mgr = OWLManager.createOWLOntologyManager();
		OWLDataFactory factory = mgr.getOWLDataFactory();
		//Load the ontology and translate the URIs into OWL API entities
		try {
			OWLOntology ontology = mgr.loadOntology(IRI.create(mPhysicalURI));
			OWLOntologyImportsClosureSetProvider provider = new OWLOntologyImportsClosureSetProvider(mgr, ontology);
			OWLOntologyMerger merger = new OWLOntologyMerger(provider);
			OWLOntology closure = merger.createMergedOntology(mgr, IRI.create(ontology.getOntologyID().toString() + "#importclosure"));
			Set<OWLEntity> signature = new HashSet<OWLEntity>(theSignature.size());
			
			for (URI termResource : theSignature) {
				OWLEntity term = OWLAPIUtils.uriToOWLEntity(ontology, factory, termResource);
				
				if (term != null) signature.add(term);
			}
			
			if (!signature.isEmpty()) {
				OntologySegmenter extractor = new SyntacticLocalityModuleExtractor(mgr, closure, mModuleType);
				OWLOntology module = extractor.extractAsOntology(signature,	IRI.create(mPhysicalURI.toString() + "#module"));
				
				System.out.println("Module extracted for " + signature + ": " + module.getLogicalAxiomCount() + " logical OWL axioms");
				
				//theSignature.clear();
				//Model jenaModel = new OWLAPIToJenaTranslator(mgr, module).getModel();

				return new OWLAPIModule(module);
				
			} else {
				return new OWLAPIModule();
			}
			
		} catch (OWLOntologyCreationException e) {
			throw new ModuleExtractionException(e);
		}
	}
}